package test.client.support;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import test.client.analyzer.Analyzer;
import test.client.support.thread.ThreadManager;

public class Watcher implements Runnable {
	private Log log = LogFactory.getLog(this.getClass());
	
	private final long sleepTime = 5000;
	private final long maxIterationCount = 3;
	
	private ThreadManager manager;
	private Analyzer analyzer;
	
	public Watcher(Analyzer analyzer, ThreadManager manager) {
		this.analyzer = analyzer;
		this.manager = manager;
	}

	@Override
	public void run() {
		int iterationCount = 0;
		int complemetedThreadCount = 0;
		boolean analyzed = false;
		
		while (iterationCount++ < this.maxIterationCount) {
			try {
				Thread.sleep(sleepTime);
			} catch (InterruptedException e) {
				e.printStackTrace();
				break;
			}
			
			log.debug("Watcher: Check if all threads done...");
			if (manager.isAllThreadDone()) {
				log.info("Watcher: All thread done... flush the table");
				
				// analyze the response time
				this.analyzer.analyze();
				analyzed = true;
				break;
			}
			else {
				log.info("Watcher: " + manager.getCompletedThreadCount() + " / " + manager.getMaxThreadCount() 
						+ " threads done. waiting other threads...");
			}
			
			if (complemetedThreadCount < manager.getCompletedThreadCount()) {
				// if changes on thread statuses, set iteration count to 0.
				complemetedThreadCount = manager.getCompletedThreadCount();
				iterationCount = 0;
			}
		}
		
		log.info("Watcher: Iteration done. Stopping all uncompleted threads if any...");
		manager.stop();
		
		log.info("Watcher is stopped.");
		
		if (!analyzed && !manager.isAllThreadDone()) {
			if (complemetedThreadCount == 0) {
				log.error("No thread run.");
				return;
			}
			
			log.error("Watcher: All thread work could not be completed. Just flush the result.");
			log.error("Watcher: Thread completed : " + complemetedThreadCount + " / " + manager.getMaxThreadCount());
			this.analyzer.analyze();
		}
	}

	public void setManager(ThreadManager manager) {
		this.manager = manager;
	}

	public void setAnalyzer(Analyzer analyzer) {
		this.analyzer = analyzer;
	}
}
